package com.github.skystardust.lotteryex.lottery;

import com.github.skystardust.lotteryex.lottery.bundle.AwardBundle;
import com.github.skystardust.lotteryex.lottery.bundle.RequireBundle;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import javax.annotation.Nonnull;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

@EqualsAndHashCode(of = "uuid")
@ToString
public class LotteryItem implements ConfigurationSerializable {
    private UUID uuid;
    private ItemStack displayItemStack;
    private List<RequireBundle> requireBundleList;
    private List<AwardBundle> awardBundleList;

    public LotteryItem(UUID uuid, ItemStack displayItemStack, List<RequireBundle> requireBundleList, List<AwardBundle> awardBundleList) {
        this.uuid = uuid;
        this.displayItemStack = displayItemStack;
        this.requireBundleList = requireBundleList;
        this.awardBundleList = awardBundleList;
    }

    public LotteryItem(Map<String, Object> stringObjectMap) {
        this.uuid = UUID.fromString(((String) stringObjectMap.get("uuid")));
        this.requireBundleList = (List<RequireBundle>) stringObjectMap.get("requireBundleList");
        this.awardBundleList = ((List<AwardBundle>) stringObjectMap.get("awardBundleList"));
        this.displayItemStack = ((ItemStack) stringObjectMap.get("displayItemStack"));
    }

    private LotteryItem(Builder builder) {
        setUuid(builder.uuid);
        displayItemStack = builder.displayItemStack;
        setRequireBundleList(builder.requireBundleList);
        setAwardBundleList(builder.awardBundleList);
    }

    public static Builder newBuilder() {
        return new Builder();
    }

    public List<RequireBundle> getRequireBundleList() {
        return requireBundleList;
    }

    public void setRequireBundleList(List<RequireBundle> requireBundleList) {
        this.requireBundleList = requireBundleList;
    }

    public List<AwardBundle> getAwardBundleList() {
        return awardBundleList;
    }

    public void setAwardBundleList(List<AwardBundle> awardBundleList) {
        this.awardBundleList = awardBundleList;
    }

    public UUID getUuid() {
        return uuid;
    }

    public void setUuid(UUID uuid) {
        this.uuid = uuid;
    }


    public boolean hasRequireItems(Player player) {
        return getRequireBundleList().stream().allMatch(requireBundle -> requireBundle.hasRequireObject(player));
    }

    public void giveAwards(Player player) {
        getAwardBundleList().forEach(awardBundle -> awardBundle.giveAward(player));
    }


    @Override
    public Map<String, Object> serialize() {
        TreeMap<String, Object> stringObjectTreeMap = new TreeMap<>();
        stringObjectTreeMap.put("uuid", uuid.toString());
        stringObjectTreeMap.put("requireBundleList", requireBundleList);
        stringObjectTreeMap.put("awardBundleList", awardBundleList);
        stringObjectTreeMap.put("displayItemStack", displayItemStack);
        return stringObjectTreeMap;
    }

    public static final class Builder {
        private UUID uuid;
        private ItemStack displayItemStack;
        private List<RequireBundle> requireBundleList;
        private List<AwardBundle> awardBundleList;

        private Builder() {
        }

        @Nonnull
        public Builder withUuid(@Nonnull UUID val) {
            uuid = val;
            return this;
        }

        @Nonnull
        public Builder withDisplayItemStack(@Nonnull ItemStack val) {
            displayItemStack = val;
            return this;
        }

        @Nonnull
        public Builder withRequireBundleList(@Nonnull List<RequireBundle> val) {
            requireBundleList = val;
            return this;
        }

        @Nonnull
        public Builder withAwardBundleList(@Nonnull List<AwardBundle> val) {
            awardBundleList = val;
            return this;
        }

        @Nonnull
        public LotteryItem build() {
            return new LotteryItem(this);
        }
    }
}
